/**
 * <a href="http://www.cpupk.com/decompiler">Eclipse Class Decompiler</a> plugin, Copyright (c) 2017 Chen Chao.
 */
/*
 *    Copyright 2009-2013 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.sql.parse.ognl;

import com.google.common.collect.Lists;
import com.sql.parse.PlaceHolder;
import com.sql.parse.type.SimpleTypeRegistry;
import org.apache.ibatis.scripting.xmltags.OgnlCache;

import java.util.Collection;
import java.util.List;

/**
 * @author GWQ
 */
public class TextSqlNode implements DataNode {
    private String text;

    public TextSqlNode(String text) {
        this.text = text;
    }

    public boolean isDynamic(Collection<PlaceHolder> placeHolders) {
        Boolean flag = true;
        for (PlaceHolder placeHolder : placeHolders) {
            DynamicCheckerTokenParser checker = new DynamicCheckerTokenParser();
            GenericTokenParser parser = createParser(checker, placeHolder);
            parser.parse(text);
            flag = checker.isDynamic();
            if (flag) {
                return flag;
            }
        }
        return flag;
    }

    @Override
    public boolean apply(MyDynamicContext context) {

        String textTmp = text;
        List<GenericTokenParser> parserList = generateParserList(context.getPlaceHolders(), new BindingTokenParser(context));
        for (GenericTokenParser parser : parserList) {
            textTmp = parser.parse(textTmp);
        }
        context.appendSql(textTmp);
        return true;
    }

    private List<GenericTokenParser> generateParserList(Collection<PlaceHolder> placeHolders, BindingTokenParser bindingTokenParser) {
        List<GenericTokenParser> genericTokenParserList = Lists.newArrayList();
        for (PlaceHolder placeHolder : placeHolders) {
            GenericTokenParser parser = createParser(bindingTokenParser, placeHolder);
            genericTokenParserList.add(parser);
        }
        return genericTokenParserList;
    }

    private GenericTokenParser createParser(TokenHandler handler, PlaceHolder placeHolder) {
        return new GenericTokenParser(placeHolder.getPrefix(), placeHolder.getSuffix(), handler);
    }

    private static class BindingTokenParser implements TokenHandler {

        private MyDynamicContext context;

        public BindingTokenParser(MyDynamicContext context) {
            this.context = context;
        }

        @Override
        public String handleToken(String content) {
            Object parameter = context.getBindings().get("_parameter");
            if (parameter == null) {
                context.getBindings().put("value", null);
            } else if (SimpleTypeRegistry.isSimpleType(parameter.getClass())) {
                context.getBindings().put("value", parameter);
            }
            Object value = OgnlCache.getValue(content, context.getBindings());
            return (value == null ? "" : String.valueOf(value)); // issue #274 return "" instead of "null"
        }
    }

    private static class DynamicCheckerTokenParser implements TokenHandler {

        private boolean isDynamic;

        public boolean isDynamic() {
            return isDynamic;
        }

        @Override
        public String handleToken(String content) {
            this.isDynamic = true;
            return null;
        }
    }

}